library(tidyverse)
load the data from prev. lesson
surveys_complete <- read_csv("/Users/rossum/Dropbox/teaching/Workshops/SCW-DCW/lessonsDC/R-ecology-lesson/data_output/surveys_complete.csv")
Challenge - scatter plot
Use what you just learned to create a scatter plot of weight over genus with the field plot types showing in different colors. Is this a good way to show this type of data?
ggplot(data = surveys_complete, mapping = aes(x = genus, y = weight)) +
geom_point(aes(color = plot_type))
Bonus challenge - overplotting
With a geom_point() plot, we couldn’t tell if 1 or 1000 points were drawn at the same location. When points overlap, this is called “overplotting” and it can hide information in a plot. We can avoid this several ways. Try recreating the weight vs hindfoot_length scatter plot with the following changes
- try replacing geom_point() with geom_bin2d()
- try adding geom_density2d() on top of geom_point()
- try replacing geom_point() with geom_point(alpha=0.2)
Which of these communicated the distribution of the data most clearly? What are their strengths and weaknesses?
Bonus bonus: google: “Rpackage hexbin” and see if you can install it and use it for an alternative plot
ggplot(data = surveys_complete, mapping = aes(x = weight, y = hindfoot_length)) +
geom_bin2d()
ggplot(data = surveys_complete, mapping = aes(x = weight, y = hindfoot_length)) +
geom_point()+geom_density2d()
ggplot(data = surveys_complete, mapping = aes(x = weight, y = hindfoot_length)) +
geom_point(alpha = 0.1)
#install.packages("hexbin")
library(hexbin)
ggplot(data = surveys_complete, mapping = aes(x = weight, y = hindfoot_length)) +
geom_hex()
Challenge: violoin plot
Boxplots are useful summaries, but they hide the shape of the distribution. For example, if the distribution is bimodal, we would not see it in a boxplot. An alternative to the boxplot is the violin plot, where the shape (of the density of points) is drawn.
- Replace the box plot with a violin plot; see
geom_violin().
In many types of data, it is important to consider the scale of the observations. For example, it may be worth changing the scale of the axis to better distribute the observations in the space of the plot. Changing the scale of the axes is done similarly to adding/modifying other components (i.e., by incrementally adding commands). Try making these modifications:
- Represent weight on the log10 scale; see
scale_y_log10().
So far, we’ve looked at the distribution of weight within genera. Try making a new plot to explore the distribution of another variable within each genus.
- Create a boxplot for
hindfoot_length. Overlay the boxplot layer on a jitter layer to show actual measurements.
Bonus challenge: variability in trend
Is the trend that we saw in the previous plot consistent for most years sampled?
medianWeightByGenusByMonthByYear <- surveys_complete %>%
group_by(year, genus, month) %>%
summarise(medianWeight = median(weight,na.rm = T))
ggplot(data = medianWeightByGenusByMonthByYear,
mapping = aes(x = month, y = medianWeight,
group = interaction(year,genus),color=genus)) +
geom_line()
# Can you find a better way to visualise an answer?
Challenge - sex diff by species?
How does the abundance of each species change through the years for females and males. (Use the variable species_id)
countsByYearBySexBySpecies <- surveys_complete %>%
group_by(year, species_id, sex) %>%
summarise(n = n())
ggplot(data = countsByYearBySexBySpecies, mapping = aes(x = year, y = n, color = sex)) +
geom_line() +
facet_wrap(.~ species_id)
Bonus challenge: investigate species “RF”
In the line plot above, species “RF” looks really weird. Take a closer look a the data for this species. Why does it look this way? You might want to try a “stacked bar chart” (see the section “Histogram on a categorical variable” on this site: http://r-statistics.co/Top50-Ggplot2-Visualizations-MasterList-R-Code.html)
surveys_complete %>%
filter(species_id %in% c("RF")) %>%
ggplot(aes(x=year,fill=sex))+geom_bar()
Challenge: weight by year
Use what you just learned to create a plot that depicts how the average weight of each genus changed through the years.
Answer
yearly_weight <- surveys_complete %>%
group_by(year, genus) %>%
summarize(weightMean = mean(weight))
ggplot(data = yearly_weight, mapping = aes(x=year, y=weightMean)) +
geom_line() +
facet_wrap(.~ genus) +
theme_bw()
Challenge: free style
With all of this information in hand, please take another five minutes to either improve one of the plots generated in this exercise or create a beautiful graph of your own. Use the RStudio ggplot2 cheat sheet for inspiration. Here are some ideas:
sessionInfo()
LS0tCnRpdGxlOiAnRGF0YSB2aXN1YWxpemF0aW9uIHdpdGggZ2dwbG90MjogQ2hhbGxlbmdlcycKYXV0aG9yOiAiVGhlYSBWYW4gUm9zc3VtIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgZGZfcHJpbnQ6IGthYmxlCiAgICB0b2M6IHllcwogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIGNvZGVfZm9sZGluZzogaGlkZQplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG89VFJVRSxldmFsPUYpCmBgYAoKYGBge3IgbG9hZC1wYWNrYWdlLCBtZXNzYWdlPUZBTFNFLCBwdXJsPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgpsb2FkIHRoZSBkYXRhIGZyb20gcHJldi4gbGVzc29uCgpgYGB7ciBsb2FkLWRhdGEsIHB1cmw9RkFMU0V9CnN1cnZleXNfY29tcGxldGUgPC0gcmVhZF9jc3YoIi9Vc2Vycy9yb3NzdW0vRHJvcGJveC90ZWFjaGluZy9Xb3Jrc2hvcHMvU0NXLURDVy9sZXNzb25zREMvUi1lY29sb2d5LWxlc3Nvbi9kYXRhX291dHB1dC9zdXJ2ZXlzX2NvbXBsZXRlLmNzdiIpCmBgYAoKCgojIENoYWxsZW5nZSAtIHNjYXR0ZXIgcGxvdAoKVXNlIHdoYXQgeW91IGp1c3QgbGVhcm5lZCB0byBjcmVhdGUgYSBzY2F0dGVyIHBsb3Qgb2YgYHdlaWdodGAgb3ZlcgpgZ2VudXNgIHdpdGggdGhlIGZpZWxkIHBsb3QgdHlwZXMgc2hvd2luZyBpbiBkaWZmZXJlbnQgY29sb3JzLiBJcyB0aGlzIGEgZ29vZAp3YXkgdG8gc2hvdyB0aGlzIHR5cGUgb2YgZGF0YT8KCmBgYHtyIHNjYXR0ZXItY2hhbGxlbmdlLCBwdXJsPUZBTFNFfQpnZ3Bsb3QoZGF0YSA9IHN1cnZleXNfY29tcGxldGUsIG1hcHBpbmcgPSBhZXMoeCA9IGdlbnVzLCB5ID0gd2VpZ2h0KSkgKwogICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IHBsb3RfdHlwZSkpCmBgYAoKCiMgQm9udXMgY2hhbGxlbmdlIC0gb3ZlcnBsb3R0aW5nCgpXaXRoIGEgYGdlb21fcG9pbnQoKWAgcGxvdCwgd2UgY291bGRuJ3QgdGVsbCBpZiAxIG9yIDEwMDAgcG9pbnRzIHdlcmUgZHJhd24gYXQgdGhlIHNhbWUgbG9jYXRpb24uIFdoZW4gcG9pbnRzIG92ZXJsYXAsIHRoaXMgaXMgY2FsbGVkICJvdmVycGxvdHRpbmciIGFuZCBpdCBjYW4gaGlkZSBpbmZvcm1hdGlvbiBpbiBhIHBsb3QuIFdlIGNhbiBhdm9pZCB0aGlzIHNldmVyYWwgd2F5cy4gVHJ5IHJlY3JlYXRpbmcgdGhlIHdlaWdodCB2cyBoaW5kZm9vdF9sZW5ndGggc2NhdHRlciBwbG90IHdpdGggdGhlIGZvbGxvd2luZyBjaGFuZ2VzCgotIHRyeSByZXBsYWNpbmcgZ2VvbV9wb2ludCgpIHdpdGggZ2VvbV9iaW4yZCgpCi0gdHJ5IGFkZGluZyBnZW9tX2RlbnNpdHkyZCgpIG9uIHRvcCBvZiBnZW9tX3BvaW50KCkgCi0gdHJ5IHJlcGxhY2luZyBnZW9tX3BvaW50KCkgd2l0aCBnZW9tX3BvaW50KGFscGhhPTAuMikKCldoaWNoIG9mIHRoZXNlIGNvbW11bmljYXRlZCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBkYXRhIG1vc3QgY2xlYXJseT8gCldoYXQgYXJlIHRoZWlyIHN0cmVuZ3RocyBhbmQgd2Vha25lc3Nlcz8KCkJvbnVzIGJvbnVzOiBnb29nbGU6ICJScGFja2FnZSBoZXhiaW4iIGFuZCBzZWUgaWYgeW91IGNhbiBpbnN0YWxsIGl0IGFuZCB1c2UgaXQgZm9yIGFuIGFsdGVybmF0aXZlIHBsb3QKCmBgYHtyIG92ZXJwbG90dGluZy1zb2xufQpnZ3Bsb3QoZGF0YSA9IHN1cnZleXNfY29tcGxldGUsIG1hcHBpbmcgPSBhZXMoeCA9IHdlaWdodCwgeSA9IGhpbmRmb290X2xlbmd0aCkpICsKICAgIGdlb21fYmluMmQoKQoKZ2dwbG90KGRhdGEgPSBzdXJ2ZXlzX2NvbXBsZXRlLCBtYXBwaW5nID0gYWVzKHggPSB3ZWlnaHQsIHkgPSBoaW5kZm9vdF9sZW5ndGgpKSArCiAgICBnZW9tX3BvaW50KCkrZ2VvbV9kZW5zaXR5MmQoKQoKZ2dwbG90KGRhdGEgPSBzdXJ2ZXlzX2NvbXBsZXRlLCBtYXBwaW5nID0gYWVzKHggPSB3ZWlnaHQsIHkgPSBoaW5kZm9vdF9sZW5ndGgpKSArCiAgICBnZW9tX3BvaW50KGFscGhhID0gMC4xKQoKI2luc3RhbGwucGFja2FnZXMoImhleGJpbiIpCmxpYnJhcnkoaGV4YmluKQpnZ3Bsb3QoZGF0YSA9IHN1cnZleXNfY29tcGxldGUsIG1hcHBpbmcgPSBhZXMoeCA9IHdlaWdodCwgeSA9IGhpbmRmb290X2xlbmd0aCkpICsKIGdlb21faGV4KCkKCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIENoYWxsZW5nZTogdmlvbG9pbiBwbG90CgpCb3hwbG90cyBhcmUgdXNlZnVsIHN1bW1hcmllcywgYnV0IHRoZXkgaGlkZSB0aGUgKnNoYXBlKiBvZiB0aGUgZGlzdHJpYnV0aW9uLiBGb3IKZXhhbXBsZSwgaWYgdGhlIGRpc3RyaWJ1dGlvbiBpcyBiaW1vZGFsLCB3ZSB3b3VsZCBub3Qgc2VlIGl0IGluIGEKYm94cGxvdC4gQW4gYWx0ZXJuYXRpdmUgdG8gdGhlIGJveHBsb3QgaXMgdGhlIHZpb2xpbiBwbG90LCB3aGVyZSB0aGUgc2hhcGUgCihvZiB0aGUgZGVuc2l0eSBvZiBwb2ludHMpIGlzIGRyYXduLgoKLSBSZXBsYWNlIHRoZSBib3ggcGxvdCB3aXRoIGEgdmlvbGluIHBsb3Q7IHNlZSBgZ2VvbV92aW9saW4oKWAuCgpJbiBtYW55IHR5cGVzIG9mIGRhdGEsIGl0IGlzIGltcG9ydGFudCB0byBjb25zaWRlciB0aGUgKnNjYWxlKiBvZiB0aGUKb2JzZXJ2YXRpb25zLiAgRm9yIGV4YW1wbGUsIGl0IG1heSBiZSB3b3J0aCBjaGFuZ2luZyB0aGUgc2NhbGUgb2YgdGhlIGF4aXMgdG8KYmV0dGVyIGRpc3RyaWJ1dGUgdGhlIG9ic2VydmF0aW9ucyBpbiB0aGUgc3BhY2Ugb2YgdGhlIHBsb3QuICBDaGFuZ2luZyB0aGUgc2NhbGUKb2YgdGhlIGF4ZXMgaXMgZG9uZSBzaW1pbGFybHkgdG8gYWRkaW5nL21vZGlmeWluZyBvdGhlciBjb21wb25lbnRzIChpLmUuLCBieQppbmNyZW1lbnRhbGx5IGFkZGluZyBjb21tYW5kcykuIFRyeSBtYWtpbmcgdGhlc2UgbW9kaWZpY2F0aW9uczoKCi0gUmVwcmVzZW50IHdlaWdodCBvbiB0aGUgbG9nfjEwfiBzY2FsZTsgc2VlIGBzY2FsZV95X2xvZzEwKClgLgoKU28gZmFyLCB3ZSd2ZSBsb29rZWQgYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiB3ZWlnaHQgd2l0aGluIGdlbmVyYS4gVHJ5IG1ha2luZyBhCm5ldyBwbG90IHRvIGV4cGxvcmUgdGhlIGRpc3RyaWJ1dGlvbiBvZiBhbm90aGVyIHZhcmlhYmxlIHdpdGhpbiBlYWNoIGdlbnVzLgoKLSBDcmVhdGUgYSBib3hwbG90IGZvciBgaGluZGZvb3RfbGVuZ3RoYC4gT3ZlcmxheSB0aGUgYm94cGxvdCBsYXllciBvbiBhIGppdHRlcgogIGxheWVyIHRvIHNob3cgYWN0dWFsIG1lYXN1cmVtZW50cy4KCgpgYGB7ciBib3hwbG90LWNoYWxsZW5nZSwgZXZhbD1GQUxTRSwgcHVybD1UUlVFLCBlY2hvPUZBTFNFfQojIyBDaGFsbGVuZ2Ugd2l0aCBib3hwbG90czoKIyMgIFN0YXJ0IHdpdGggdGhlIGJveHBsb3Qgd2UgY3JlYXRlZDoKZ2dwbG90KGRhdGEgPSBzdXJ2ZXlzX2NvbXBsZXRlLCBtYXBwaW5nID0gYWVzKHggPSBnZW51cywgeSA9IHdlaWdodCkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjMpCgojIyAgMS4gUmVwbGFjZSB0aGUgYm94IHBsb3Qgd2l0aCBhIHZpb2xpbiBwbG90OyBzZWUgYGdlb21fdmlvbGluKClgLgoKZ2dwbG90KGRhdGEgPSBzdXJ2ZXlzX2NvbXBsZXRlLCBtYXBwaW5nID0gYWVzKHggPSBnZW51cywgeSA9IHdlaWdodCkpICsKICBnZW9tX2ppdHRlcihhbHBoYSA9IDAuMykrCiAgZ2VvbV92aW9saW4oKQoKIyMgIDIuIFJlcHJlc2VudCB3ZWlnaHQgb24gdGhlIGxvZzEwIHNjYWxlOyBzZWUgYHNjYWxlX3lfbG9nMTAoKWAuCgpnZ3Bsb3QoZGF0YSA9IHN1cnZleXNfY29tcGxldGUsIG1hcHBpbmcgPSBhZXMoeCA9IGdlbnVzLCB5ID0gd2VpZ2h0KSkgKwogIGdlb21faml0dGVyKGFscGhhID0gMC4zKSsKICBnZW9tX3Zpb2xpbigpICsgCiAgc2NhbGVfeV9sb2cxMCgpCgojIyAgMy4gQ3JlYXRlIGJveHBsb3QgZm9yIGBoaW5kZm9vdF9sZW5ndGhgIG92ZXJsYWlkIG9uIGEgaml0dGVyIGxheWVyLgoKZ2dwbG90KGRhdGEgPSBzdXJ2ZXlzX2NvbXBsZXRlLCBtYXBwaW5nID0gYWVzKHggPSBnZW51cywgeSA9IGhpbmRmb290X2xlbmd0aCkpICsKICBnZW9tX2ppdHRlcihhbHBoYSA9IDAuMykrCiAgZ2VvbV9ib3hwbG90KCkgCgpgYGAKCgojIEJvbnVzIGNoYWxsZW5nZTogYm94IHBsb3QgYWx0ZXJuYXRpdmVzCgpjaGVjayBvdXQgaHR0cHM6Ly93d3cuci1ncmFwaC1nYWxsZXJ5LmNvbS9hbGwtZ3JhcGhzLwpJcyB0aGVyZSBhbm90aGVyIGxpYmFyeSB0aGF0IHlvdSBjb3VsZCBkb3dubG9hZCBhbmQgdXNlIHRvIG1ha2Ugc29tZSBuaWNlIHBsb3RzPwoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIENoYWxsZW5nZTogbGluZSBwbG90IC0gbWVkaWFuIHdlaWdodCBieSBtb250aAoKRG9lcyB0aGUgbWVkaWFuIHdlaWdodCBwZXIgZ2VudXMgY2hhbmdlIG92ZXIgdGhlIHllYXI/IGUuZy4gYXJlIHRoZXJlIHNvbWUgbW9udGhzIHdoZW4gYW5pbWFscyB0ZW5kIHRvIGJlIGhlYXZpZXI/IEZvciBzaW1wbGljaXR5LCBjb25zaWRlciB0aGUgbWVkaWFuIHdlaWdodCBhY3Jvc3MgYWxsIHllYXJzLiAKCmBgYHtyIHRpbWUtc2VyaWVzLXdpdGgtY29sb3JzLCBwdXJsPUZBTFNFfQoKbWVkaWFuV2VpZ2h0QnlHZW51c0J5TW9udGggPC0gc3VydmV5c19jb21wbGV0ZSAlPiUKICBncm91cF9ieShnZW51cywgbW9udGgpICU+JSAKICBzdW1tYXJpc2UobWVkaWFuV2VpZ2h0ID0gbWVkaWFuKHdlaWdodCxuYS5ybSA9IFQpKQoKZ2dwbG90KGRhdGEgPSBtZWRpYW5XZWlnaHRCeUdlbnVzQnlNb250aCwgCiAgICAgICBtYXBwaW5nID0gYWVzKHggPSBtb250aCwgeSA9IG1lZGlhbldlaWdodCwgY29sb3IgPSBnZW51cykpICsKICAgIGdlb21fbGluZSgpCgpgYGAKCiMgQm9udXMgY2hhbGxlbmdlOiB2YXJpYWJpbGl0eSBpbiB0cmVuZAoKSXMgdGhlIHRyZW5kIHRoYXQgd2Ugc2F3IGluIHRoZSBwcmV2aW91cyBwbG90IGNvbnNpc3RlbnQgZm9yIG1vc3QgeWVhcnMgc2FtcGxlZD8gCgpgYGB7ciB0aW1lLXNlcmllcy13aXRoLWNvbG9ycy1tdWx0aWxpbmUsIHB1cmw9RkFMU0V9CgptZWRpYW5XZWlnaHRCeUdlbnVzQnlNb250aEJ5WWVhciA8LSBzdXJ2ZXlzX2NvbXBsZXRlICU+JQogIGdyb3VwX2J5KHllYXIsIGdlbnVzLCBtb250aCkgJT4lIAogIHN1bW1hcmlzZShtZWRpYW5XZWlnaHQgPSBtZWRpYW4od2VpZ2h0LG5hLnJtID0gVCkpCgpnZ3Bsb3QoZGF0YSA9IG1lZGlhbldlaWdodEJ5R2VudXNCeU1vbnRoQnlZZWFyLCAKICAgICAgIG1hcHBpbmcgPSBhZXMoeCA9IG1vbnRoLCB5ID0gbWVkaWFuV2VpZ2h0LCAKICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBpbnRlcmFjdGlvbih5ZWFyLGdlbnVzKSxjb2xvcj1nZW51cykpICsKICBnZW9tX2xpbmUoKQoKIyBDYW4geW91IGZpbmQgYSBiZXR0ZXIgd2F5IHRvIHZpc3VhbGlzZSBhbiBhbnN3ZXI/CgpgYGAKCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIENoYWxsZW5nZSAtIHNleCBkaWZmIGJ5IHNwZWNpZXM/CgpIb3cgZG9lcyB0aGUgYWJ1bmRhbmNlIG9mIGVhY2ggKnNwZWNpZXMqIGNoYW5nZSB0aHJvdWdoIHRoZSB5ZWFycyBmb3IgZmVtYWxlcyBhbmQgbWFsZXMuIChVc2UgdGhlIHZhcmlhYmxlIGBzcGVjaWVzX2lkYCkKCmBgYHtyfQoKY291bnRzQnlZZWFyQnlTZXhCeVNwZWNpZXMgPC0gc3VydmV5c19jb21wbGV0ZSAlPiUKICBncm91cF9ieSh5ZWFyLCBzcGVjaWVzX2lkLCBzZXgpICU+JSAKICBzdW1tYXJpc2UobiA9IG4oKSkKCiBnZ3Bsb3QoZGF0YSA9IGNvdW50c0J5WWVhckJ5U2V4QnlTcGVjaWVzLCBtYXBwaW5nID0gYWVzKHggPSB5ZWFyLCB5ID0gbiwgY29sb3IgPSBzZXgpKSArCiAgICAgZ2VvbV9saW5lKCkgKwogICAgIGZhY2V0X3dyYXAoLn4gc3BlY2llc19pZCkKIApgYGAKCiMgQm9udXMgY2hhbGxlbmdlOiBpbnZlc3RpZ2F0ZSBzcGVjaWVzICJSRiIKCkluIHRoZSBsaW5lIHBsb3QgYWJvdmUsIHNwZWNpZXMgIlJGIiBsb29rcyByZWFsbHkgd2VpcmQuIFRha2UgYSBjbG9zZXIgbG9vayBhIHRoZSBkYXRhIGZvciB0aGlzIHNwZWNpZXMuIFdoeSBkb2VzIGl0IGxvb2sgdGhpcyB3YXk/IApZb3UgbWlnaHQgd2FudCB0byB0cnkgYSAic3RhY2tlZCBiYXIgY2hhcnQiIChzZWUgdGhlIHNlY3Rpb24gIkhpc3RvZ3JhbSBvbiBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlIiBvbiB0aGlzIHNpdGU6IGh0dHA6Ly9yLXN0YXRpc3RpY3MuY28vVG9wNTAtR2dwbG90Mi1WaXN1YWxpemF0aW9ucy1NYXN0ZXJMaXN0LVItQ29kZS5odG1sKQoKYGBge3J9CnN1cnZleXNfY29tcGxldGUgJT4lIAogIGZpbHRlcihzcGVjaWVzX2lkICVpbiUgYygiUkYiKSkgJT4lIAogIGdncGxvdChhZXMoeD15ZWFyLGZpbGw9c2V4KSkrZ2VvbV9iYXIoKQpgYGAKCgojIENoYWxsZW5nZTogd2VpZ2h0IGJ5IHllYXIgCgpVc2Ugd2hhdCB5b3UganVzdCBsZWFybmVkIHRvIGNyZWF0ZSBhIHBsb3QgdGhhdCBkZXBpY3RzIGhvdyB0aGUgYXZlcmFnZSB3ZWlnaHQKb2YgZWFjaCBnZW51cyBjaGFuZ2VkIHRocm91Z2ggdGhlIHllYXJzLgoKYGBge3IgYXZlcmFnZS13ZWlnaHQtdGltZS1zZXJpZXMsIGFuc3dlcj1UUlVFLCBwdXJsPUZBTFNFfQogeWVhcmx5X3dlaWdodCA8LSBzdXJ2ZXlzX2NvbXBsZXRlICU+JQogICAgICAgICAgICAgICAgIGdyb3VwX2J5KHllYXIsIGdlbnVzKSAlPiUKICAgICAgICAgICAgICAgICAgc3VtbWFyaXplKHdlaWdodE1lYW4gPSBtZWFuKHdlaWdodCkpCiBnZ3Bsb3QoZGF0YSA9IHllYXJseV93ZWlnaHQsIG1hcHBpbmcgPSBhZXMoeD15ZWFyLCB5PXdlaWdodE1lYW4pKSArCiAgICBnZW9tX2xpbmUoKSArCiAgICBmYWNldF93cmFwKC5+IGdlbnVzKSArCiAgICB0aGVtZV9idygpCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgQ2hhbGxlbmdlOiBmcmVlIHN0eWxlCgpXaXRoIGFsbCBvZiB0aGlzIGluZm9ybWF0aW9uIGluIGhhbmQsIHBsZWFzZSB0YWtlIGFub3RoZXIgZml2ZSBtaW51dGVzIHRvCmVpdGhlciBpbXByb3ZlIG9uZSBvZiB0aGUgcGxvdHMgZ2VuZXJhdGVkIGluIHRoaXMgZXhlcmNpc2Ugb3IgY3JlYXRlIGEKYmVhdXRpZnVsIGdyYXBoIG9mIHlvdXIgb3duLiBVc2UgdGhlIFJTdHVkaW8gWyoqYGdncGxvdDJgKiogY2hlYXQgc2hlZXRdKGh0dHBzOi8vd3d3LnJzdHVkaW8uY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDE2LzExL2dncGxvdDItY2hlYXRzaGVldC0yLjEucGRmKQpmb3IgaW5zcGlyYXRpb24uIEhlcmUgYXJlIHNvbWUgaWRlYXM6CgoqIFNlZSBpZiB5b3UgY2FuIGNoYW5nZSB0aGUgdGhpY2tuZXNzIG9mIHRoZSBsaW5lcy4KKiBDYW4geW91IGZpbmQgYSB3YXkgdG8gY2hhbmdlIHRoZSBuYW1lIG9mIHRoZSBsZWdlbmQ/IFdoYXQgYWJvdXQgaXRzIGxhYmVscz8KKiBUcnkgdXNpbmcgYSBkaWZmZXJlbnQgY29sb3IgcGFsZXR0ZSAoc2VlIGh0dHA6Ly93d3cuY29va2Jvb2stci5jb20vR3JhcGhzL0NvbG9yc18oZ2dwbG90MikvKS4KCgpgYGB7ciBzZXNzaW9uSW5mb30Kc2Vzc2lvbkluZm8oKQpgYGA=